home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / snip9503 / serial.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  11KB  |  344 lines

  1. /*
  2. +----------------------------------------------------+
  3. |               Thunderbird Software                 |
  4. +----------------------------------------------------+
  5. | Filespec  :  Serial.c                              |
  6. | Date      :  October 24, 1991                      |
  7. | Time      :  15:03                                 |
  8. | Revision  :  1.1                                   |
  9. |     Update: August 29, 1994                        |
  10. +----------------------------------------------------+
  11. | Programmer:  Scott Andrews                         |
  12. | Address   :  5358 Summit RD SW                     |
  13. | City/State:  Pataskala, Ohio                       |
  14. | Zip       :  43062                                 |
  15. +----------------------------------------------------+
  16. | Released to the Public Domain                      |
  17. +----------------------------------------------------+
  18. */
  19.  
  20. /*
  21. +----------------------------------------------------------+
  22. |  Call open_serial to install the interrupt handler       |
  23. |  You must call close_serial before exiting your program  |
  24. |  or a machine crash will occur!                          |
  25. +----------------------------------------------------------+
  26. */
  27.  
  28. #include <stdlib.h>
  29. #include <dos.h>
  30. #include <string.h>
  31. #include "serial.h"
  32. #include "queue.h"
  33. #include "portable.h"
  34.  
  35. QUEUE *Serial_In_Queue;
  36. QUEUE *Serial_Out_Queue;
  37.  
  38. OLD_COMM_PARAMS old_comm_params;
  39. COMM_STATUS     comm_status;
  40.  
  41. void (_interrupt _far *oldvector_serial )(); 
  42. /* save addr for intr handler */
  43.  
  44. int  ComBase;                        /* Comm port address */
  45. int  IrqNum;                         /* Comm interrupt request */
  46.  
  47. int OpenComPort ( char Port )        /* install int. handler */
  48. {
  49.       unsigned status;
  50.       int retval = -1;
  51.     
  52.       /* allocate input and output queues */
  53.  
  54.       Serial_In_Queue = alloc_queue( SerInBufSize );
  55.       if ( (QUEUE *) 0 == Serial_In_Queue)
  56.             return retval;
  57.       Serial_Out_Queue = alloc_queue( SerOutBufSize );
  58.       if ( (QUEUE *) 0 == Serial_Out_Queue)
  59.       {
  60.             free ( Serial_In_Queue );
  61.             return retval;
  62.       }
  63.       retval = 0;
  64.  
  65.       /* Setup Comm base port address and IRQ number */
  66.  
  67.       switch ( Port)
  68.       {
  69.             case '1': ComBase = 0x3F8; IrqNum = 4; break;
  70.             case '2': ComBase = 0x2F8; IrqNum = 3; break;
  71.             case '3': ComBase = 0x3E8; IrqNum = 4; break;
  72.             case '4': ComBase = 0x2E8; IrqNum = 3; break;
  73.             default : ComBase = 0x3F8; IrqNum = 4; break;
  74.       }
  75.       old_comm_params.int_enable = IN_PORT ( ComBase + INT_EN );
  76.       OUT_PORT ( ComBase + INT_EN, 0 ); /* turn off comm interrupts */
  77.  
  78.       /* save old comm parameters */
  79.  
  80.       old_comm_params.line = IN_PORT ( ComBase + LINE_CNTRL );
  81.       old_comm_params.modem = IN_PORT ( ComBase + MODEM_CNTRL );
  82.       status = IN_PORT ( ComBase + LINE_CNTRL );
  83.       OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status | 0x80 );
  84.       old_comm_params.baud_lsb = IN_PORT ( ComBase + BAUD_LSB );
  85.       old_comm_params.baud_msb = IN_PORT ( ComBase + BAUD_MSB );
  86.       status = IN_PORT ( ComBase + LINE_CNTRL );
  87.       OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status | 0x7F );
  88.       status = OUT2 | DTR;              /* DTR/OUT2 must be set! */
  89.       OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
  90.  
  91.       /* get serial port address/vector */
  92.  
  93.       oldvector_serial = (void(_interrupt _far *)(void))GETVECT(IrqNum + 8 );
  94.  
  95.       /* set our interrupt handler */
  96.  
  97.       SETVECT ( IrqNum + 8, serial );
  98.  
  99.       /* save the PIC */
  100.  
  101.       old_comm_params.int_cntrl = IN_PORT ( 0x21 );
  102.       status = ( 1 << IrqNum);      /* calculate int enable bit */
  103.       status = ~status;
  104.  
  105.       /* ok enable comm ints */
  106.  
  107.       OUT_PORT ( 0x21, (unsigned char) old_comm_params.int_cntrl & 
  108.             (unsigned char) status );
  109.       return retval;
  110. }
  111.  
  112. void CloseComPort ( void )
  113. {
  114.       int status;
  115.  
  116.       /* restore UART to previous state */
  117.  
  118.       OUT_PORT ( ComBase + INT_EN, (unsigned char) 0 );
  119.       OUT_PORT ( ComBase + MODEM_CNTRL, 
  120.             (unsigned char) old_comm_params.modem );
  121.       status = IN_PORT ( ComBase + LINE_CNTRL );
  122.       OUT_PORT ( ComBase + LINE_CNTRL, 
  123.             (unsigned char) status | 0x80 );
  124.       OUT_PORT ( ComBase + BAUD_LSB, 
  125.             (unsigned char) old_comm_params.baud_lsb );
  126.       OUT_PORT ( ComBase + BAUD_MSB, 
  127.             (unsigned char) old_comm_params.baud_msb );
  128.       OUT_PORT ( ComBase + LINE_CNTRL, 
  129.             (unsigned char) old_comm_params.line );
  130.       OUT_PORT ( 0x21, (unsigned char) old_comm_params.int_cntrl );
  131.  
  132.       /* restore old interrupt handler */
  133.  
  134.       SETVECT ( IrqNum + 8, oldvector_serial );
  135.  
  136.       /* free input and output queues */
  137.  
  138.       free ( Serial_In_Queue );
  139.       free ( Serial_Out_Queue );
  140.       return;
  141. }
  142.  
  143. void InitComPort ( char Baud[], char Databits, 
  144.                    char Parity, char Stopbits )
  145. {
  146.       int status;
  147.       long baudrate;
  148.       unsigned divisor;
  149.  
  150.       /* set baud rate */
  151.  
  152.       status = IN_PORT ( ComBase + LINE_CNTRL );
  153.       OUT_PORT ( ComBase + LINE_CNTRL, 
  154.             (unsigned char) status | 0x80 );
  155.       baudrate = atol ( Baud );
  156.       if ( baudrate == 0)
  157.             baudrate = 2400L;
  158.       divisor = (unsigned) ( 115200L / baudrate);
  159.       OUT_PORT ( ComBase + BAUD_LSB, 
  160.             (unsigned char) ( divisor & 0x00FF) );
  161.       OUT_PORT ( ComBase + BAUD_MSB, 
  162.             (unsigned char) ( ( divisor >> 8) & 0x00FF) );
  163.       status = 0x00;
  164.  
  165.       /* set parity */
  166.  
  167.       switch ( Parity)                    /* set parity value     */
  168.       {
  169.       case 'O':                           /* odd parity           */
  170.       case 'o':
  171.             status = 0x08; break;
  172.  
  173.       case 'E':                           /* even parity          */
  174.       case 'e':
  175.             status = 0x18; break;
  176.  
  177.       case 'S':                           /* stick parity         */
  178.       case 's':
  179.             status = 0x28; break;
  180.  
  181.       case 'N':                           /* no parity            */
  182.       case 'n':
  183.             default :   status = 0x00;
  184.       }
  185.  
  186.     /* set number data bits */
  187.  
  188.       switch ( Databits)
  189.       {
  190.       case '5':
  191.             break;
  192.  
  193.       case '6':
  194.             status = status | 0x01;
  195.             break;
  196.  
  197.       case '7':
  198.             status = status | 0x02;
  199.             break;
  200.  
  201.       case '8':
  202.       default :
  203.             status = status | 0x03;
  204.       }
  205.  
  206.       /* set number stop bits */
  207.  
  208.       switch ( Stopbits)
  209.       {
  210.       case '2':
  211.             status = status | 0x04;
  212.             break;
  213.  
  214.       case '1':
  215.       default :
  216.             ;
  217.       }
  218.       OUT_PORT ( ComBase + LINE_CNTRL, (unsigned char) status );
  219.       status = OUT2 | DTR;        /* DTR/OUT2 must be set! */
  220.       OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
  221.  
  222.       /* enable serial interrupts */
  223.  
  224.       OUT_PORT ( ComBase + INT_EN, RX_INT | ERR_INT | RS_INT );
  225.       return;
  226. }
  227.  
  228. void DropDtr ( void )
  229. {
  230.       int status;
  231.  
  232.       status = IN_PORT ( ComBase + MODEM_CNTRL );
  233.       status &= 0xFE;                 /* turn off DTR bit */
  234.       OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
  235.       return;
  236. }
  237.  
  238. void RaiseDtr ( void )
  239. {
  240.       int status;
  241.  
  242.       status = IN_PORT ( ComBase + MODEM_CNTRL );
  243.       status |= 0x01;                  /* turn on DTR bit */
  244.       OUT_PORT ( ComBase + MODEM_CNTRL, (unsigned char) status );
  245.       return;
  246. }
  247.  
  248. int ComRecChar ( void )
  249. {
  250.       return de_queue ( Serial_In_Queue );
  251. }
  252.  
  253. int ComSendString ( char *string )
  254. {
  255.       int retval;
  256.       char *pointer;
  257.       pointer = string;
  258.  
  259.       while ( *pointer)
  260.       {
  261.             retval = en_queue ( Serial_Out_Queue, *pointer );
  262.             pointer++;
  263.       }
  264.       if ( 0x0 == (comm_status.modem & 0x40))
  265.             RaiseDtr ();
  266.       OUT_PORT ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
  267.       return retval;
  268. }
  269.  
  270. int ComSendChar ( char character )
  271. {
  272.       int retval;
  273.  
  274.       /* interrupt driven send */
  275.  
  276.       if ( 0x0 == (comm_status.modem & 0x40))
  277.             RaiseDtr ();
  278.       retval = en_queue ( Serial_Out_Queue, character );
  279.       if ( - 1 != retval)
  280.             OUT_PORT ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
  281.       return retval;
  282. }
  283.  
  284. int ComStatus ( void )
  285. {
  286.       unsigned status;
  287.       unsigned retval;
  288.  
  289.       retval = IN_PORT ( ComBase + LINE_STATUS );
  290.       retval = retval << 8;
  291.       status = IN_PORT ( ComBase + MODEM_STATUS );
  292.       retval = retval | status;
  293.       if ( queue_empty ( Serial_In_Queue ))
  294.             retval &= 0xFEFF;
  295.       else  retval |= 0x0100;
  296.       return (int) retval;
  297. }
  298.  
  299. void _interrupt _far serial ( void )            /* interrupt handler */
  300. {
  301.       int temp;
  302.  
  303.       INT_OFF ();
  304.       while ( 1)
  305.       {
  306.             comm_status.intrupt = IN_PORT ( ComBase + INT_ID );
  307.             comm_status.intrupt &= 0x0f;
  308.             switch ( comm_status.intrupt)
  309.             {
  310.             case 0x00:                 /* modem interrupt */
  311.                   comm_status.modem = IN_PORT( ComBase + MODEM_STATUS );
  312.                   break;
  313.  
  314.             case 0x02:                 /* xmit interrupt */
  315.                   if ( queue_empty ( Serial_Out_Queue ))
  316.                         OUT_PORT(ComBase + INT_EN, RX_INT|ERR_INT|RS_INT );
  317.                   else
  318.                   {
  319.                         temp = de_queue ( Serial_Out_Queue );
  320.                         if ( - 1 != temp)
  321.                               OUT_PORT ( ComBase + XMIT, temp );
  322.                   }
  323.                   break;
  324.  
  325.             case 0x04:                 /* receive interrupt */
  326.                   en_queue(Serial_In_Queue, (char)IN_PORT(ComBase + REC));
  327.                   break;
  328.  
  329.             case 0x06:                 /* line interrupt */
  330.                   comm_status.line = IN_PORT ( ComBase + LINE_STATUS );
  331.                   (void) IN_PORT ( ComBase + REC );
  332.                   en_queue ( Serial_In_Queue, '!' );
  333.                   break;
  334.  
  335.             default:                   /* No Mo` Left */
  336.                   comm_status.modem = IN_PORT ( ComBase + MODEM_STATUS );
  337.                   OUT_PORT ( 0x20, 0x20 );
  338.                   INT_ON ();
  339.                   return;
  340.             }   /* switch */
  341.       }   /* while */
  342. }
  343. /* End of Serial.C */
  344.